#ifndef _CIRCLE_LINK_LIST_H_
#define _CIRCLE_LINK_LIST_H_

#include "LinkList.h"

namespace MySTL
{

template < typename T >
class CircleLinkList : public LinkList<T>
{
public:
	~CircleLinkList();

	bool insert(int n, const T& value);
	bool insert(const T& value);
	bool remove(int n);
	bool get(int n, T& value) const;
	T& get(int n);
	const T& get(int n) const;
	bool set(int n, const T& value);
	void clear();

	T& operator [](int n);
	const T& operator [](int n) const;

	bool move(int n, int step = 1);
	bool next();

protected:
	typedef typename LinkList<T>::Node Node;
	int mod(int n) const;
	void last_to_first();
};

template < typename T >
CircleLinkList<T>::~CircleLinkList()
{
	clear();
}

template < typename T >
bool CircleLinkList<T>::insert(int n, const T& value)
{
	n = n % (this->m_length + 1);
	bool ret = LinkList<T>::insert(n, value);

	if (ret && n == 0)
	{
		last_to_first();
	}

	return ret;
}

template < typename T >
bool CircleLinkList<T>::insert(const T& value)
{
	return insert(this->m_length, value);
}

template < typename T >
bool CircleLinkList<T>::remove(int n)
{
	n = mod(n);
	bool ret = (n >= 0) && (n < this->m_length);

	if (ret)
	{
		if (n == 0)
		{
			Node* current = this->position(n);
			Node* toDel = current->next;

			if (toDel != toDel->next)
			{
				current->next = toDel->next;

				if (this->m_current == toDel)
				{
					this->m_current = toDel->next;
				}
			}
			else
			{
				current->next = NULL;
				this->m_current = NULL;
			}

			--this->m_length;

			last_to_first();

			this->destory_node(toDel);
		}
		else
		{
			ret = LinkList<T>::remove(n);
		}
	}

	return ret;
}

template < typename T >
bool CircleLinkList<T>::get(int n, T& value) const
{
	return LinkList<T>::get(mod(n), value);
}

template < typename T >
T& CircleLinkList<T>::get(int n)
{
	return LinkList<T>::get(mod(n));
}

template < typename T >
const T& CircleLinkList<T>::get(int n) const
{
	return LinkList<T>::get(mod(n));
}

template < typename T >
bool CircleLinkList<T>::set(int n, const T& value)
{
	return LinkList<T>::set(mod(n), value);
}

template < typename T >
void CircleLinkList<T>::clear()
{
	while (this->m_length > 1)
	{
		remove(1);
	}

	if (this->m_length == 1)
	{
		remove(0);
	}
}

template < typename T >
T& CircleLinkList<T>::operator [](int n)
{
	return LinkList<T>::operator [](mod(n));
}

template < typename T >
const T& CircleLinkList<T>::operator [](int n) const
{
	return LinkList<T>::operator [](mod(n));
}

template < typename T >
bool CircleLinkList<T>::move(int n, int step)
{
	return LinkList<T>::move(mod(n), step);
}

template < typename T >
bool CircleLinkList<T>::next()
{
	int step = mod(this->m_step);
	int i = 0;
	for (; i < step && !this->end(); ++i)
	{
		this->m_current = this->m_current->next;
	}

	return i == step;
}

template < typename T >
int CircleLinkList<T>::mod(int n) const
{
	return this->m_length > 0 ? n % this->m_length : 0;
}

template < typename T >
void CircleLinkList<T>::last_to_first()
{
	Node* last = this->position(this->m_length - 1)->next;

	if (NULL != last)
	{
		last->next = this->m_header.next;
	}
}

}

#endif